from typing import Any, AsyncIterator
from agents.doc_agent import create_document_agent, process_document
from core.exception import ApiException
from models.doc_schemas import DocumentRequest
from tools.document_tools import DocumentTools
import gc  # 垃圾回收模块，用于手动释放内存
import logging  # 日志模块，用于记录程序运行状态

# 初始化日志记录器，指定当前模块名称
logger = logging.getLogger(__name__)


class DocumentService:
    """文档处理服务类，负责接收文档请求并进行流式处理

    主要功能：
    1. 初始化文档处理所需的工具和智能体
    2. 接收文档请求，按规则分割长文档
    3. 调用智能体处理文档内容并返回流式结果
    """

    def __init__(self):
        """类初始化方法，创建工具集和文档处理智能体"""
        # 初始化文档处理工具集（如文档获取、解析等工具）
        self.tools = DocumentTools.create_tools()

        # 基于工具集创建文档处理智能体（负责实际的文档分析、总结等逻辑）
        self.agent = create_document_agent(self.tools)

    # 流式处理文档请求
    async def process_document_stream(self, request: DocumentRequest) -> AsyncIterator[str]:
        """异步流式处理文档请求，返回迭代器形式的处理结果

        Args:
            request: 文档处理请求对象，包含文档URL、处理要求等参数

        Returns:
            异步迭代器，逐个返回文档处理后的内容片段
        """
        # 处理文档
        try:
            # 记录开始处理文档的日志
            logger.info("开始处理文档")

            # 获取文档内容：通过工具类从请求的URL中拉取文档
            doc_content = DocumentTools.fetch_document(str(request.url))

            # 提取文档内容文本（假设返回的字典中"content"键对应文档正文）
            content = doc_content["content"]

            # 用于存储文档分割后的片段
            chunks = []

            # 判断文档长度是否超过100,000字符，超过则需要分割处理
            if len(content) >= 100000:
                logger.info(f"文档长度超过100000，开始分割处理")

                # 初始化当前块变量，用于累积不足100,000字符的内容
                current_chunk = ""

                # 遍历内容中的每个段落，使用'\n\n'（两个换行符）作为段落分隔符
                for paragraph in content.split('\n\n'):
                    # 检查当前块加上新段落后是否超过100,000字符，且当前块非空
                    if len(current_chunk) + len(paragraph) > 100000 and current_chunk:
                        # 将当前块添加到块列表中，并以当前段落开始新的块
                        chunks.append(current_chunk)
                        current_chunk = paragraph
                    else:
                        # 否则，将当前段落添加到当前块中
                        # 若当前块非空，添加段落前先加两个换行符作为分隔
                        current_chunk = f"{current_chunk}\n\n{paragraph}" if current_chunk else paragraph

                # 循环结束后，若当前块仍有内容，将其添加到块列表
                if current_chunk:
                    chunks.append(current_chunk)

            else:
                # 文档长度未超过阈值，无需分割，直接作为一个块
                chunks = [content]

            # 遍历每个文档块进行处理
            for i, chunk in enumerate(chunks):
                # 构建智能体处理所需的输入文本，整合文档信息和处理要求
                input_text = self._build_input_text(
                    doc_content["title"],
                    chunk,
                    request.summary_type,
                    request.language,
                    request.length or "无限制",
                    request.additional_instructions or "无"
                )

                # 异步处理当前文本块，通过智能体生成结果
                # process_document返回异步迭代器，逐段获取处理结果
                async for chunk in process_document(self.agent, input_text):
                    # 将处理结果片段返回给调用方
                    yield chunk


                if i < len(chunks) - 1:
                    yield "\n\n-----------下一部分------------\n\n"


                gc.collect()


        except Exception as e:
            # 捕获处理过程中的所有异常，打印并返回错误信息
            print(e)
            yield f"文档处理失败{e}"

    # 私有方法：构建输入块
    def _build_input_text(self, title: str, content: str, summary_type: str,
                          language: str, length: int, additional_instructions: str) -> str:
        """构建智能体处理所需的输入文本，整合文档信息和处理参数

        Args:
            title: 文档标题
            content: 文档内容片段
            summary_type: 总结类型
            language: 输出语言
            length: 输出最大长度
            additional_instructions: 额外处理要求

        Returns:
            格式化后的输入文本字符串
        """
        return f"""
               文档标题: {title}
               文档内容: {content}
               总结类型: {summary_type}
               输出语言: {language}
               最大长度: {length}
               额外要求: {additional_instructions}
               """